﻿using System;
using System.Collections.Generic;
using Should;
using mesan.ansatte.domain.Enities;
using mesan.ansatte.domain.interfaces;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using Moq;



namespace mesan.ansatt.services.unittests
{
    /// <summary>
    /// Summary description for AnsattService
    /// </summary>
    [TestClass]
    public class AnsatteServiceTests
    {
        private AnsatteService _instance;
        private Mock<IAnsatteRepository> _repoMock;

        [TestInitialize]
        public void BeForeEachTest()
        {
            _repoMock = new Mock<IAnsatteRepository>();
            _instance = new AnsatteService(_repoMock.Object);
        }

        [TestMethod]
        public void GetAll_WhenCalled_ReturnsListOfAnsatte()
        {
          

            // Act
            var result = _instance.GetAll();
            
            // Assert
          
            result.ShouldBeType<List<Ansatt>>();
        }

        [TestMethod]
        public void GetAll_WhenCalled_UsesRepoClass()
        {
            // Act
           _instance.GetAll();

            // Assert
            _repoMock.Verify(o => o.GetAll(), Times.Once());
        }

        [TestMethod]
        public void GetById_IdIsEmpty_ReturnsNull()
        {
            // Act
            var result = _instance.GetById(string.Empty);

            // Assert
            result.ShouldBeNull();
        }

        [TestMethod]
        public void GetById_IdIsValid_ReturnsAnsatt()
        {
            // Arrange
            var randomId = Guid.NewGuid().ToString();
            var ansatt = new Ansatt();
            _repoMock.Setup(o => o.GetById(randomId)).Returns(ansatt);

            // Act
            var result = _instance.GetById(randomId);

            // Assert
            result.ShouldBeSameAs(ansatt);
        }

        [TestMethod]
        public void GetById_IdIsUnknown_ReturnsNull()
        {
            // Arrange
            var randomId = Guid.NewGuid().ToString();
           

            // Act
            var result = _instance.GetById(randomId);

            // Assert
            result.ShouldBeNull();
        }

        [TestMethod]
        public void GetById_RepositoryThrowsException_ReturnsNull()
        {
            // Arrange
            var randomId = Guid.NewGuid().ToString();
            var e = new Exception();
            _repoMock.Setup(o => o.GetById(randomId)).Throws(e);


            // Act
            var result = _instance.GetById(randomId);

            // Assert
            result.ShouldBeNull();
        }
        
        [TestMethod]
        public void GetAll_RepositoryThrowsException_ReturnsEmptyList()
        {
            // Arrange
            var e = new Exception();
            _repoMock.Setup(o => o.GetAll()).Throws(e);

            // Act
            var result = _instance.GetAll();

            // Assert
            result.ShouldBeEmpty();
        }

		[TestMethod]
		public void GetByShoenumber_ShoeNumberIsNegative_ReturnsEmptyList()
		{
			// Arrange

			// Act
			var result = _instance.GetByShoenumber(-1);

			// Assert
			result.ShouldBeEmpty();
		}

		[TestMethod]
		public void GetByShoenumber_ShoeNumberIsNegative_DoesNotUseRepo()
		{
			// Act
			var result = _instance.GetByShoenumber(-1);

			// Assert
			_repoMock.Verify(o => o.GetAll(), Times.Never());
		}

		[TestMethod]
		public void GetByShoenumber_RepoThrowsException_ReturnsEmptyList()
		{
			// Arrange
			var e = new Exception();
			_repoMock.Setup(o => o.GetAll()).Throws(e);

			// Act
			var result = _instance.GetByShoenumber(27);

			// Assert
			result.ShouldBeEmpty();
		}

		[TestMethod]
		public void GetByShoenumber_NoShoenumbersMatch_ResultIsEmptyList()
		{
			// Arrange
			var fakeResult = new List<Ansatt> {
				new Ansatt{ Skonummer = 41 },
	            new Ansatt{ Skonummer = 42 },
                new Ansatt{ Skonummer = 44 },
      			new Ansatt{ Skonummer = 43 },
			};
			_repoMock.Setup(o => o.GetAll()).Returns(fakeResult);

			// Act
			var result = _instance.GetByShoenumber(27);

			// Assert
			result.ShouldBeEmpty();
		}

		[TestMethod]
		public void GetByShoenumber_GivenNumberMatchesTwoOfFive_ResultIsListWithTwoEntries()
		{
			// Arrange
			var fakeResult = new List<Ansatt> {
				new Ansatt{ Skonummer = 44},
				new Ansatt{ Skonummer = 41},
				new Ansatt{ Skonummer = 42},
				new Ansatt{ Skonummer = 44},
				new Ansatt{ Skonummer = 43},
			};
			_repoMock.Setup(o => o.GetAll()).Returns(fakeResult);

			// Act
			var result = _instance.GetByShoenumber(44);

			// Assert
			result.Count.ShouldEqual(2);
		}

		[TestMethod]
		public void GetByShoenumber_ShoenumberIsUnrealisticallyHigh_DoesNotUseRepository()
		{
			// Act
			var result = _instance.GetByShoenumber(60);

			// Assert
			_repoMock.Verify(o => o.GetAll(), Times.Never());
		}
    }
}
